import java.util.Random;


public class Effect {

	public EffectType type;
	public Target relativeTarget;
	public double amount;
	private Type element;
	/*
	 * This keeps track of how much of an effect actually happened
	 */
	private int modifier;
	
	/*
	 * This is the "blabla hit blabla for x points" message
	 */
	private String description;
	
	public Effect(EffectType type, int strength) {
		this.type = type;
		this.amount = strength;
		this.description = "";
		this.relativeTarget = Target.Other;
	}
	
	public Effect(EffectType type, Target relativeTarget, double amount, Type element) {
		this.type = type;
		this.element = element;
		this.amount = amount;
		this.description = "";
		this.relativeTarget = relativeTarget;
	}
	
	public String getDescription() {
		if (description != "") {
			return description;
		} else {
			throw new UnsupportedOperationException("You haven't performed the effect yet!");
		}
	}
	
	public int perform(Pet source, Pet target) {
		 int accuracy = (int) (85 + (source.speed - target.speed) + target.size*0.05);
		 if(accuracy > 95)
		 accuracy = 95;												//hur man rï¿½knar ut accuracy
		 else if (accuracy < 60)
		 accuracy = 60;
		 
		Random r = new Random();
		int randomInt = r.nextInt(100) + 1;
		int catchInt = r.nextInt(100) + 1;
		 
		int previous;
		switch (type) {
		case AddDefense:
			target.defense = (int) (target.defense + amount);
			modifier = (int) amount;
			description = target.getName() + " har bättre försvar nu med " + Integer.toString(modifier) + " poäng.";
			break;
		case AddHealth:
			previous = target.damageTaken;
			target.damageTaken = (int) Math.max(0, target.damageTaken - amount);
			modifier = previous - target.damageTaken;
			description = target.getName() + " blev helad för " + Integer.toString(modifier) + " hälsa av " + source.getName() + ".";
			break;
		case AddSize:
			previous = target.size;
			target.size = (int) Math.min(50, target.size + amount);
			modifier = target.size - previous;
			description = target.getName() + " har blivit större.";
			break;
		case AddSpeed:
			target.speed = (int) (target.speed + amount);
			modifier = (int) (amount);
			description = target.getName() + " är mycket snabbare. Meep Meep!";
			break;
		case AddStrength:
			target.strength = (int) (target.strength + amount);
			modifier = (int) amount;
			description = target.getName() + " blev starkare. Så manligt!";
			break;
		case CatchTarget: 
			int prob;
			int probability = (int) (100 - (target.getCurrentHealth() / target.getMaxHealth())/0.01 - target.speed/4.0);
				if(probability > catchInt){
					prob = 1;
					return prob;
				}
					
				else {
					prob = 0;
					return prob;
				}
		case RemoveHealth:

			if(accuracy > randomInt){
				previous = target.damageTaken;
				// TODO: Fixa detta så att den skadar mer på
				// högre levlar.
				double multiplier = Math.exp(source.strength*0.0167);
				if (r.nextInt(100) < 30) {
					switch(element){
					case Fire:
						if(target.element == Type.Water)
							multiplier *= 0.5;
						else if(target.element == Type.Nature)
							multiplier *= 1.5;
					break;
					case Water:
						if(target.element == Type.Energy)
							multiplier *= 0.5;
						else if(target.element == Type.Fire)
							multiplier *= 1.5;
					break;
					case Nature:
						if(target.element == Type.Fire)
							multiplier *= 0.5;
						else if(target.element == Type.Energy)
							multiplier *= 1.5;
					break;
					case Energy:
						if(target.element == Type.Nature)
							multiplier *= 0.5;
						else if(target.element == Type.Water)
							multiplier *= 1.5;
					break;
					}
				}
				
				double wobblef = amount*multiplier*0.2 * r.nextDouble() - amount*multiplier*0.1;
				int wobble = (int) Math.round(wobblef);
				target.damageTaken = (int) Math.min(target.getMaxHealth(), target.damageTaken + Math.max(1, amount*multiplier + wobble));
				modifier = target.damageTaken - previous;
				description = target.getName() + " blev skadad för " + modifier + " hälsa av " + source.getName() + "!";
			}
			else {
				modifier = -1;
				description = source.getName() + " missade sin attack!";
			}
			break;
		case RemoveSize:
			previous = target.size;
			target.size = (int) Math.max(10, target.size - amount);
			modifier = previous - target.size;
			break;
		case RemoveSpeed:
			previous = target.speed;
			target.speed = (int) Math.max(5, target.speed - amount);
			modifier = previous - target.speed;
			description = target.getName() + " blev retarderad.";
			break;
		case RemoveDefense:
			previous = target.defense;
			target.defense = (int) Math.max(5, target.defense - amount);
			modifier = previous - target.defense;
			description = target.getName() + " är svagare.";
			break;
		case RemoveStrength:
			previous = target.strength;
			target.strength = (int) Math.max(5, target.strength - amount);
			modifier = previous - target.strength;
			description = target.getName() + " är svagare.";
			break;
		default:
			throw new UnsupportedOperationException("That effect is not implemented yet!");
		}
		
		return modifier;
	}
	
}
